package com.mdd.admin.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.github.yulichang.query.MPJQueryWrapper;
import com.mdd.admin.LikeAdminThreadLocal;
import com.mdd.admin.service.IOrderService;
import com.mdd.admin.validate.order.DishAddValidate;
import com.mdd.admin.validate.order.OrderSubmitValidate;
import com.mdd.admin.validate.order.OrdersCreateValidate;
import com.mdd.admin.vo.order.OrderDeskVo;
import com.mdd.admin.vo.order.OrderDishCateVo;
import com.mdd.admin.vo.order.OrderDishVo;
import com.mdd.common.config.GlobalConfig;
import com.mdd.common.entity.article.Article;
import com.mdd.common.entity.article.ArticleCategory;
import com.mdd.common.entity.orders.Orders;
import com.mdd.common.entity.orders.OrdersDish;
import com.mdd.common.entity.orders.OrdersDishListVo;
import com.mdd.common.entity.shop.Printer;
import com.mdd.common.entity.system.SystemAuthDept;
import com.mdd.common.enums.PrintEnum;
import com.mdd.common.mapper.article.ArticleCategoryMapper;
import com.mdd.common.mapper.article.ArticleMapper;
import com.mdd.common.mapper.orders.OrdersDishMapper;
import com.mdd.common.mapper.orders.OrdersMapper;
import com.mdd.common.mapper.shop.PrinterMapper;
import com.mdd.common.mapper.system.SystemAuthDeptMapper;
import com.mdd.common.util.*;
import me.chanjar.weixin.common.util.crypto.SHA1;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.*;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;

@Service

public class OrderServiceImpl implements IOrderService {

    @Resource
    private SystemAuthDeptMapper systemAuthDeptMapper;
    @Resource
    private ArticleCategoryMapper articleCategoryMapper;
    @Resource
    private ArticleMapper articleMapper;
    @Resource
    private OrdersMapper ordersMapper;
    @Resource
    private OrdersDishMapper ordersDishMapper;
    @Resource
    private PrinterMapper printerMapper;


    @Override
    public List<OrderDeskVo> list() {
        Integer aid = LikeAdminThreadLocal.getAdminId();

        MPJQueryWrapper<SystemAuthDept> mpjQueryWrapper = new MPJQueryWrapper<SystemAuthDept>()
                .selectAll(SystemAuthDept.class)
                .select("post.name as area")
                .innerJoin("?_system_auth_post post ON post.id=t.area_id".replace("?_", GlobalConfig.tablePrefix))
                .eq("t.is_delete", 0)
                .eq("t.is_stop",0)
                .eq("t.aid", aid)
                .orderByDesc(Arrays.asList("t.sort", "t.id"));

        List<OrderDeskVo> orderDeskVos = systemAuthDeptMapper.selectJoinList(OrderDeskVo.class, mpjQueryWrapper);
        for (OrderDeskVo orderDeskVo : orderDeskVos) {
            orderDeskVo.setCreateTime(TimeUtils.timestampToDate(orderDeskVo.getCreateTime()));
            orderDeskVo.setUpdateTime(TimeUtils.timestampToDate(orderDeskVo.getUpdateTime()));
        }
        return orderDeskVos;
    }

    @Override
    public List<OrderDishCateVo> dishCate() {
        Integer aid = LikeAdminThreadLocal.getAdminId();
        QueryWrapper<ArticleCategory> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("aid",aid);
        queryWrapper.eq("is_delete",0);
        queryWrapper.eq("is_show",1);
        List<ArticleCategory> articleCategories = articleCategoryMapper.selectList(queryWrapper);
        List<OrderDishCateVo> orderDishCateVos = new ArrayList<>();
        for (ArticleCategory articleCategory : articleCategories){
            OrderDishCateVo orderDishCateVo = new OrderDishCateVo();
            orderDishCateVo.setName(articleCategory.getName());
            orderDishCateVo.setSort(articleCategory.getSort());
            orderDishCateVo.setId(articleCategory.getId());
            orderDishCateVos.add(orderDishCateVo);
        }
        return orderDishCateVos;

    }

    @Override
    public List<OrderDishVo> dishList(String name) {
        Integer aid = LikeAdminThreadLocal.getAdminId();
        MPJQueryWrapper<Article> mpjQueryWrapper=null;
        if(!StringUtils.isEmpty(name)){
          mpjQueryWrapper = new MPJQueryWrapper<Article>()
                .selectAll(Article.class)
                .select("ac.name as category")
                .innerJoin("?_article_category ac ON ac.id=t.cid".replace("?_", GlobalConfig.tablePrefix))
                .eq("t.is_delete", 0)
                .eq("t.aid",aid)
                .eq("t.is_show",1)
                .like("t.title",name)
                .orderByDesc(Arrays.asList("t.sort", "t.id"));
        }else{
            mpjQueryWrapper = new MPJQueryWrapper<Article>()
                    .selectAll(Article.class)
                    .select("ac.name as category")
                    .innerJoin("?_article_category ac ON ac.id=t.cid".replace("?_", GlobalConfig.tablePrefix))
                    .eq("t.is_delete", 0)
                    .eq("t.aid",aid)
                    .eq("t.is_show",1)
                    .orderByDesc(Arrays.asList("t.sort", "t.id"));
        }
        List<OrderDishVo> orderDishVos = articleMapper.selectJoinList(OrderDishVo.class, mpjQueryWrapper);
        String engine = ConfigUtils.get("storage", "default", "local");
        engine = engine.equals("") ? "local" : engine;
        for (OrderDishVo orderDishVo : orderDishVos){
            if (engine.equals("local")) {
                orderDishVo.setImage(RequestUtils.uri()+orderDishVo.getImage());
            } else if (engine.equals("aliyun")) {
                orderDishVo.setImage(orderDishVo.getImage());
            }else{
                orderDishVo.setImage(UrlUtils.toAbsoluteUrl(orderDishVo.getImage()));
            }

            orderDishVo.setCreateTime(TimeUtils.timestampToDate(orderDishVo.getCreateTime()));
            orderDishVo.setUpdateTime(TimeUtils.timestampToDate(orderDishVo.getUpdateTime()));
        }
        return orderDishVos;

    }

    /**
     * 创建订单
     * @param ordersCreateValidate
     */
    @Override
    public Integer ordersCreate(OrdersCreateValidate ordersCreateValidate) {
        Orders orders = new Orders();
        orders.setUserNum(ordersCreateValidate.getUserNum());//就餐人数
//        orders.setNumber(UUID.randomUUID().toString());
        String yyyyMMdd = TimeUtils.timestampToDate(System.currentTimeMillis() / 1000, "yyyyMMddHHmmss");
        Long timestamp = TimeUtils.getCurrentDayTime();
        // 订单号
        orders.setNumber(yyyyMMdd+ordersCreateValidate.getDeskId());
        orders.setDeskId(ordersCreateValidate.getDeskId());//桌号id
        orders.setType(ordersCreateValidate.getType());
        orders.setStatus(0);//待下单状态
        orders.setAid(LikeAdminThreadLocal.getAdminId());
        orders.setCreateTime(TimeUtils.timestamp());
        ordersMapper.insert(orders);
        return orders.getId();
    }

    @Override
    public Integer dishAdd(DishAddValidate dishAddValidate) {
        OrdersDish ordersDish = new OrdersDish();
        ordersDish.setDishId(dishAddValidate.getDishId());
        ordersDish.setOrderId(dishAddValidate.getOrderId());
        ordersDish.setQuantity(1);
        ordersDish.setOrderFlag("1");
        ordersDish.setCreateTime(TimeUtils.timestamp());
        Article one = articleMapper.selectOne(new QueryWrapper<Article>().eq("id", dishAddValidate.getDishId()));
        ordersDish.setAmount(new BigDecimal(one.getSummary()));
        ordersDishMapper.insert(ordersDish);
        return ordersDish.getId();
    }

    @Override
    public void dishInc(Integer id) {
        // 通过ID查询  订单ID和菜品ID   查询当前菜品的状态  如果order_flag =2，证明已经下过单了，则新加一条数据
        OrdersDish ordersDish = ordersDishMapper.selectById(id);
        String orderFlag = ordersDish.getOrderFlag();
        if("1".equals(orderFlag)){
            // 如果未下单，则直接添加
            ordersDishMapper.dishInc(id);
        } else {
            // 查询相同菜品 相同订单ID
            Integer noCommitOrder = ordersDishMapper.getNoCommitOrder(ordersDish.getOrderId(), ordersDish.getDishId());
            if(noCommitOrder!=null){
                dishInc(noCommitOrder);
            }else{
                // 查询相同菜品 相同订单ID 添加
                DishAddValidate newValidate = new DishAddValidate();
                newValidate.setOrderId(ordersDish.getOrderId());
                newValidate.setDishId(ordersDish.getDishId());
                dishAdd(newValidate);
            }
        }

    }

    @Override
    public void dishDec(Integer id) {
        // 查询有几条数据。如果只有1条，直接减一
        OrdersDish dishAndOrderInfo = ordersDishMapper.getDishAndOrderInfo(id);
        List<OrdersDish> dishAndOrderListInfo = ordersDishMapper.getDishAndOrderListInfo(dishAndOrderInfo.getOrderId(), dishAndOrderInfo.getDishId());
        if(CollectionUtils.isNotEmpty(dishAndOrderListInfo)){
            OrdersDish ordersDish = dishAndOrderListInfo.get(0);
            if(ordersDish.getQuantity()>1){
                // 如果有多个，则减一
                ordersDishMapper.dishDec(ordersDish.getId());
            }else{
                // 如果只有一个，则删除掉
                ordersDishMapper.dishDel(ordersDish.getId());
            }
        }
    }

    @Override
    public void dishDel(Integer id) {
        ordersDishMapper.dishDel(id);
    }

    @Override
    public List<OrdersDishListVo>  toEmpty(Integer id) {
        List<OrdersDishListVo> emptyInfoByOrderId = ordersDishMapper.getEmptyInfoByOrderId(id);
        ordersDishMapper.delete(new QueryWrapper<OrdersDish>().eq("order_id",id).eq("order_flag","1"));
        return emptyInfoByOrderId;
    }

    @Override
    public void submit(OrderSubmitValidate orderSubmitValidate) {
        // 查询订单状态是否已结账   如果已结账，只打印前台单，重新更新订单信息
        Orders orders1 = ordersMapper.selectById(orderSubmitValidate.getNumber());
        Integer status = orders1.getStatus();
        if(status==2){
            //  结账后加菜
            List<OrdersDishListVo> ordersDishListVos = ordersDishMapper.getorderList(orderSubmitValidate.getNumber(),null);
            Orders orders = new Orders();
            orders.setId(orderSubmitValidate.getNumber());
            orders.setRemark(orderSubmitValidate.getRemark());
            orders.setAmount(ordersDishMapper.compute(orderSubmitValidate.getNumber()).toString());
            // 将所有已下单的菜品状态修改为2
            ordersDishMapper.updateOrderFlag(orderSubmitValidate.getNumber());
            // 更新餐桌信息
            ordersMapper.updateById(orders);
            // 打印小票
            getprintInfo(orders,ordersDishListVos,"only");
        }else{
            // 查询订单状态为 1 的数据
            List<OrdersDishListVo> ordersDishListVos = ordersDishMapper.getorderList(orderSubmitValidate.getNumber(),"1");

            Orders orders = new Orders();
            orders.setId(orderSubmitValidate.getNumber());
            orders.setStatus(1);//待结帐就餐中
            orders.setRemark(orderSubmitValidate.getRemark());
            orders.setAmount(ordersDishMapper.compute(orderSubmitValidate.getNumber()).toString());
            // 将所有已下单的菜品状态修改为2
            ordersDishMapper.updateOrderFlag(orderSubmitValidate.getNumber());
            // 更新餐桌信息
            ordersMapper.updateById(orders);
            // 打印小票
            getprintInfo(orders,ordersDishListVos,null);
        }

    }

    public void getprintInfo(Orders orders,List<OrdersDishListVo> ordersDishListVos,String only) {
        // 出小票
        Integer id = orders.getId();
        // 获取打印机信息
        List<Printer> printerByOrderId = printerMapper.getPrinterByOrderId(id,only);
        String nickname = ordersMapper.getnickName(id);
        // 获取桌号名称和当前人数
        Map<String, String> diskNameAndNum = ordersMapper.getDiskNameAndNum(id);
//        "userNum" -> "2" "name" -> "2007"
        for (Printer item:printerByOrderId) {
            Integer mode = item.getMode();
            String content=getModeInfo(mode);
            // 打印内容拼接 {#nickname} {#meony}  {#createDate}  {#remark}     {#content}
            String replaceContext = montageContent(mode,nickname,orders.getRemark(), ordersDishListVos, content);
            if(replaceContext.contains("{#content}")){
               break;
            }
            String userNum = String.valueOf(diskNameAndNum.get("userNum"));
            String diskname = diskNameAndNum.get("name");
            if(!StringUtils.isEmpty(userNum)){
                replaceContext= replaceContext.replace("{#number}", userNum);
            }
            if(!StringUtils.isEmpty(userNum)){
                replaceContext= replaceContext.replace("{#diskname}", diskname);
            }
            // 打印机SN码
            String secret = item.getSecret();
            // 执行打印方法
            printExecution(secret,replaceContext);
        }
    }

    /**
     *
     * @param nickname  商户名称
     * @param remark 备注
     * @param ordersDishListVos 订单信息
     * @param content 内容
     * @return
     */
    private String montageContent(Integer mode,String nickname, String remark, List<OrdersDishListVo> ordersDishListVos, String content) {
        String orderDetil ="";
        BigDecimal meony =BigDecimal.valueOf(0l);
        BigDecimal meonyres =BigDecimal.valueOf(0l);
        for (OrdersDishListVo vo:ordersDishListVos) {
            String name = vo.getName();
            BigDecimal amount = vo.getAmount();
            Integer number = vo.getNumber();
            // 0 前台  1后厨
            //<L><lr>Яйца с помидорами</L><lc><HT><R>   19.9</R><BR>
            //<L><lr>Жаренная желтая говядина</L><lc><HT><R>   50</R><BR>
            if(mode==0||mode==1){
                orderDetil+="<L><lr>"+name+"<lc><HT>"+number+"<R>   "+amount+"</R><BR>";
            }else{
                orderDetil+="<L><lr>"+name+"<lc><HT><R>   "+number+"</R><BR>";
            }
            meony=meony.add(BigDecimal.valueOf(number).multiply(amount));
        }
        if(!StringUtils.isEmpty(nickname)){
            content= content.replace("{#nickname}", nickname);
        }
        if(!StringUtils.isEmpty(orderDetil)){
            content= content.replace("{#content}", orderDetil);
        }
            content = content.replace("{#meony}", meony.toString());
        meonyres=meony.multiply(new BigDecimal("0.1"));
        // 设置小数位数为 0（即取整），并使用四舍五入（ROUND_HALF_UP）模式
        meonyres = meonyres.setScale(0, BigDecimal.ROUND_HALF_UP);
        meonyres=meony.add(meonyres);
        content = content.replace("{#meonyRes}", meonyres.toString());

        remark= remark==null?"":remark;
        content = content.replace("{#createDate}", TimeUtils.timestampToDate(System.currentTimeMillis() / 1000));
        return content.replace("{#remark}", remark);
    }

    private void printExecution(String secret,String content) {
//        String url ="https://open.xpyun.net/api/openapi/xprinter/print";
        String url ="https://gm.open.xpyun.net/api/openapi/xprinter/print";
        JSONObject jsonObject = new JSONObject();
        String  user = "306132416@qq.com";
        long timestamp = Instant.now().getEpochSecond();
        String userkey = "d6418389641b417ca7078f531e7be86a";
        String  sign = String.format("%s%s%s",user,userkey,timestamp);
        String gen = SHA1.gen(sign);
        jsonObject.put("user",user);
        jsonObject.put("timestamp",timestamp);
        jsonObject.put("sign",gen);
        jsonObject.put("debug","0");
        jsonObject.put("sn",secret);
        jsonObject.put("content",content);
        jsonObject.put("copies","1");
        jsonObject.put("voice","2");
        String s = HttpUtils.sendPost(url, jsonObject.toJSONString());
        System.out.println(s);
        JSONObject ret = JSONObject.parseObject(s);
        try {
            returnMsg(ret);
        }catch (Exception e){
        }
    }

    private String  getModeInfo(Integer mode) {
            String filePath="";
        if(mode==1){
            filePath="/modeInfo/print01";
        }else if(mode==0){
            filePath="/modeInfo/checkout";
        }else{
            filePath="/modeInfo/print02";
        }
            InputStream inputStream = OrderServiceImpl.class.getResourceAsStream(filePath);
            if (inputStream!= null) {
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
                    String collect = reader.lines().collect(Collectors.joining(System.lineSeparator()));
                    return collect;
                }catch (Exception e){
                }
                return "";
            }
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        return null;
    }

    @Override
    public void checkout(Integer did) {
        Assert.notNull(did,"结账失败失败，缺少id值");
        Integer orderId = ordersMapper.getOrderId(did);
        String nickName = ordersMapper.getnickName(orderId);
        // 查询当前订单所有数据
        List<OrdersDishListVo> ordersDishListVos = ordersDishMapper.getorderList(orderId,null);
        // 订单为空结账，则该订单为无效订单，删除订单
        if(CollectionUtils.isEmpty(ordersDishListVos)){
            ordersMapper.deleteOrderId(orderId);
            return;
        }
        List<String> printSNCode = printerMapper.getPrintSNCode(orderId);
        // 重新计算金额
        BigDecimal compute = ordersDishMapper.compute(orderId);
        ordersMapper.updateOrdersStatusAndMeony(orderId,TimeUtils.timestamp(),compute);
        String content=getModeInfo(0);
        String contentRes = montageContent(0,nickName,"", ordersDishListVos, content);
        // 如果内容没有信息，则不执行打印
        if(contentRes.contains("{#content}")){
            return;
        }
        for (String str:printSNCode) {
            checkoutPrint(str, contentRes);
        }
    }

    @Override
    public Map<String,String> getUpOrderId(Integer diskId) {
        return ordersDishMapper.getUpOrderByDiskId(diskId);
    }

    @Override
    public Map<String, String> getOrderStatistics(Integer aid, String type,List<Integer> childIds) {
        if (aid == null) {
            return null;
        }
        // 查询当前商家子商家
        List<Integer> currentAidChindId=new ArrayList<>();
        if(!CollectionUtils.isEmpty(childIds)){
            currentAidChindId=childIds;
            aid=null;
        }else{
            currentAidChindId = ordersMapper.getCurrentAidChindId("," + aid + ",");
        }
        List<Long> time;
        if(!StringUtils.isEmpty(type)){
            time = new ArrayList<>();
            List<String> list = Arrays.asList(type.split("[,]"));
            list.forEach(timeStr->{
                Long l = Long.parseLong(timeStr);
                time.add(l);
            });
        }else{
            time = TimeUtils.getLongTime();
        }
        return ordersDishMapper.getOrderStatistics(aid,currentAidChindId,time.get(0),time.get(1));
    }

    private void checkoutPrint(String printSNCode, String contentRes) {
//        String url ="https://open.xpyun.net/api/openapi/xprinter/print";
        String url ="https://gm.open.xpyun.net/api/openapi/xprinter/print";

        JSONObject jsonObject = new JSONObject();
        String  user = "306132416@qq.com";
        long timestamp = Instant.now().getEpochSecond();
        String userkey = "d6418389641b417ca7078f531e7be86a";
        String  sign = String.format("%s%s%s",user,userkey,timestamp);

        String gen = SHA1.gen(sign);

        jsonObject.put("user",user);
        jsonObject.put("timestamp",timestamp);
        jsonObject.put("sign",gen);
        jsonObject.put("debug","0");
        jsonObject.put("sn",printSNCode);
        jsonObject.put("content",contentRes);
        jsonObject.put("copies","1");
        jsonObject.put("voice","2");

        String s = HttpUtils.sendPost(url, jsonObject.toJSONString());
        System.out.println(s);
        JSONObject ret = JSONObject.parseObject(s);
        returnMsg(ret);
    }

    private String returnMsg(JSONObject ret){
        PrintEnum[] values = PrintEnum.values();
        String res="";
        for (PrintEnum code : values) {
            String code1 = code.getCode();
            if(code1.equals(ret.getString("code"))){
                res= "zh".equals(LikeAdminThreadLocal.get("defaultLanguage"))?code.getMsgZh():code.getMsgRu();
                break;
            }
        }
        return res;
    }
}
